/*********************************************************************************
 *      Copyright:  (C) 2019 Wu Yujun<540726307@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  pdu_sms.c
 *    Description:  This file packet pdu sms
 *                 
 *        Version:  1.0.0(2019年07月27日)
 *         Author:  Wu Yujun <540726307@qq.com>
 *      ChangeLog:  1, Release initial version on "2019年07月27日 09时16分35秒"
 *                 
 ********************************************************************************/
#include "pdu_sms.h"

/************************************************************************************************  
 *  Describe:format receiver sms phone number for send pdu sms
 *
 *  Input parameter: 
 *              const char *center_num is string of center sms phone number
 *              const char *rec_num is string of receiver sms phone number
 *              const char *mess is message content by Unicode ,mess content must be Unicode!!!
 *  Output parameter:
 *              char *out_str is after packet pdu sms 
 *  Return:
 *          OK return send length for AT+CMGS=${Send Length}; Fail return negative
 *************************************************************************************************/
int packet_pdu_sms(const char *center_num, const char *rec_num, const char *mess, char *out_str, int out_size)
{
    int     rv = -1 ;
    char    center[64] ;
    char    receiver[64] ;
    char    sms_mess[512] ;
    int     sms_length = 0;
    int     cmgs_len = 0 ;


    if(!center_num || !rec_num || !mess || !out_str || out_size <= 0)
    {
        printf("Invail paremeter in %s\n", __FUNCTION__) ;
        return -1 ;
    }
    memset(center, 0, sizeof(center)) ;
    rv = format_center_num(center_num, center, sizeof(center)) ;
    if(rv < 0)
    {
        printf("format center sms phone number error\n") ;
        return -2 ;
    }
    memset(receiver, 0, sizeof(receiver)) ;
    rv = format_receive_num(rec_num, receiver, sizeof(receiver)) ;
    if(rv < 0)
    {
        printf("format receiver phone number error\n") ;
        return -3 ;
    }

    sms_length = strlen(mess) ;
    sms_length = sms_length/2 ;
    memset(sms_mess, 0, sizeof(sms_mess)) ;
    if(sms_length<16)
    {
        snprintf(sms_mess, sizeof(sms_mess),"0%x%s",sms_length,mess) ;
    }
    else{
        snprintf(sms_mess, sizeof(sms_mess),"%x%s",sms_length,mess) ;
    }
    snprintf(out_str, out_size,"%s%s%s", center,receiver,sms_mess) ;
    cmgs_len = strlen(receiver)+strlen(sms_mess) ;
    cmgs_len = cmgs_len/2;

    return cmgs_len ;
}


/************************************************************************
 *  Describe:format receiver sms phone number for send pdu sms
 *
 *  Input parameter: 
 *              const char *rec_num is string of receiver sms phone number
 *  Output parameter:
 *              char *out_str is after format receiver sms phone number output 
 *  Return:
 *          OK return 0; Fail return negative
 ***********************************************************************/
int format_receive_num(const char *rec_num,char *out_str, int out_size) 
{
    const char      *ptr = NULL ;
    char            temp_str[64] ;
    int             rv = -1 ;
    int             length = 0 ;

    if( !rec_num || !out_str || out_size <= 0)
    {
        printf("Invail parameter in %s\n", __FUNCTION__) ;
        return -1 ;
    }
    memset(temp_str, 0, sizeof(temp_str)) ;
    rv = format_phone_num(rec_num, temp_str, sizeof(temp_str)) ;
    if(rv < 0)
    {
        printf("format_phone_num %s fail in %s\n",rec_num, __FUNCTION__) ;
        return -2 ;
    }

    ptr = rec_num ;
    if(ptr[0] == '+')
    {
        ptr = ptr+1 ;
        if( !(*ptr) )
        {
            printf("invail receive phone number:%s\n",rec_num) ;
            return -3 ;
        }
    }
    length = strlen(ptr) ; //Length of the receive phone number
    /* "1100" and "000800" are fixed prefixes and suffixes of the receiver phone number
     *  if the number of the receiver is mobile phone, it will add "91", if it is PHS add "81"*/
    if(length < 16) 
    {
        snprintf(out_str, out_size, "11000%x91%s000800", length, temp_str) ;
    }
    else
    {
        snprintf(out_str, out_size,"1100%x91%s000800", length, temp_str);
    }
    return 0 ;
}


/************************************************************************
 *  Describe:format center sms phone number for send pdu sms
 *
 *  Input parameter: 
 *              const char *center_num is string of center sms phone number
 *  Output parameter:
 *              char *out_str is after format center sms phone number output 
 *  Return:
 *          OK return 0; Fail return negative
 ***********************************************************************/
int format_center_num(const char *center_num,char *out_str, int out_size) 
{
    char            temp_str[64] ;
    int             rv = -1 ;
    int             length = 0 ;

    if( !center_num || !out_str || out_size <= 0)
    {
        printf("Invail parameter in %s\n", __FUNCTION__) ;
        return -1 ;
    }

    memset(temp_str, 0, sizeof(temp_str)) ;
    rv = format_phone_num(center_num, temp_str, sizeof(temp_str)) ;
    if(rv < 0)
    {
        printf("format_phone_num %s fail in %s\n",center_num, __FUNCTION__) ;
        return -2 ;
    }

    length = strlen(temp_str) ;
    length = length + 2 ; //Add the number 91 logo of Internationalization in the head 
    length = length/2 ;//Length divided by 2(hex values)
    if(length < 16)
    {
        snprintf(out_str, out_size, "0%x91%s", length, temp_str) ;
    }
    else
    {
        snprintf(out_str, out_size,"%x91%s", length, temp_str);
    }

    return 0 ;
}


/************************************************************************************
 *  Describe:fomatt phone_number for send pdu sms , Delete '+', 
 *      if string is odd add 'F', and swap the odd position and even position 
 * 
 *  Input parameter: 
 *                  char *phone_num,phone_number string you want to format
 *
 *  Output parameter:
 *                  char *out_str, After fomat phone number string output to out_str
 *  Return :
 *          Successful retrun 0; Fail return negative
 ***********************************************************************************/
int format_phone_num(const char *phone_num, char *out_str, int out_size)
{
    const char      *ptr = NULL ;
    int             len = 0 ;
    char            temp_out[64] ;
    int             rv ;

    if(!phone_num || !out_str || out_size<=0 )
    {
        printf("Invail parameter in %s\n",__FUNCTION__) ;
        return -1 ;
    }
    ptr = phone_num ;
    if(ptr[0] == '+') //if have '+' Delete '+'
    {
        ptr = ptr+1 ;
        if( !(*ptr) )//if ptr point end of string "/0"
        {
            printf("Invail phone number\n") ;
            return -2 ;
        }
    }
    memset(temp_out, 0, sizeof(temp_out)) ;
    snprintf(temp_out, sizeof(temp_out), "%s", ptr) ;
    len = strlen(ptr) ;
    if( (len % 2) != 0) //if phone number string is odd, add 'F' in the last
    {
        strncat(temp_out, "F", sizeof(temp_out)) ;
    }
    rv = swap_odd_even(temp_out, strlen(temp_out), out_str, out_size) ;
    if(rv < 0)
    {
        printf("swap phone number strings the odd position and even position of the neighbour failed\n") ;
        return -3 ;
    }

    return 0 ;
}


/*****************************************************************************
 *  Describe:swap strings the odd position and even position of the neighbour
 *  
 *  Input parameter:
 *                  const char *str, the string you want to swap
 *                  int str_len, strlen of the string , it must be even
 *                  int out_str, char *str_out size, output string size
 *  Output parameter:
 *                  char *str, the string after swap output to char *str_out
 *
 *  Return:Successful return 0, Fail return negative
 *****************************************************************************/
int swap_odd_even(const char *str,int str_len, char *str_out, int out_size)
{
    int         i ;
    char        temp ;

    if( !str || str_len <= 0 || !str_out|| out_size < str_len)
    {
        printf("Invail input parameter in %s\n",__FUNCTION__) ;
        return -1 ;
    }
    if( str_len % 2 )//The string is odd
    {
        printf("Please input a size of string is even\n") ;
        return -2 ;
    }
    snprintf(str_out, out_size, "%s", str) ;
    for( i = 0; i < str_len-1; i = i+2 )
    {
        temp = str_out[i] ;
        str_out[i] = str_out[i+1] ;
        str_out[i+1] = temp ;
    }
    return 0 ;
}

